// PGLDataVectors.h: interface for the CPGLDataVectors class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_PGLDATAVECTORS_H__2D102127_B7D4_4614_A440_0DF7151346D1__INCLUDED_)
#define AFX_PGLDATAVECTORS_H__2D102127_B7D4_4614_A440_0DF7151346D1__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <pgl/core/PGLData.h>

/*!
	\defgroup PGLTempVectorGroup Vector, based on STL vector.
\ingroup PGLDataGroup
*/

/*! \brief Virtual vector template

  A classical vector object, based on STL vector. There are several constructors and cast to transform this object
  to/from vector<>.

  \ingroup PGLTempVectorGroup
*/
template <typename T>
class PGLCORE_EXT_CLASS CPGLVector : public CPGLData
{
public:
	//! \name Type definition
	//@{
	typedef T value_type;
	typedef T& reference;
	//! Vector of T
	typedef std::vector<T> VectorT;
	//@}

	//! \name Constructors
	//@{
	//! Default constructor
	CPGLVector()										{};
	//! Construct a vector of size n
	CPGLVector(size_t n): m_v(n)						{};
	//! Construct a vector from v
	CPGLVector(const VectorT& v): m_v(v)		{};
	//! Construct from array
	CPGLVector(const value_type* v, size_t n)
	{
		if (!v || n==0)
		{
			m_v.clear();
			return;
		}
	
		m_v.resize(n);
		for (size_t i = 0;i<n;++i)
			m_v[i]=v[i];
	};
	//! Copy constructor
	CPGLVector(const CPGLVector<value_type>& v)				{	*this = v;};
	//! Assignment constructor
	CPGLVector& operator = (const CPGLVector<value_type>& v)	
	{ if (this != &v) {m_v = v.m_v;} return *this;};
	virtual ~CPGLVector()									{ m_v.clear();};
	//@}

	//! \name Virtual overrides
	//@{
	//! return the size of the vector
	size_t size() const						{	return m_v.size();};
	//! index accessor
	float operator [](size_t i)	const		{	return at(i);};
	//!  accessing an elelment of the vector
	float at(size_t i) const				
	{	ASSERT(i<m_v.size()); return static_cast<float>( m_v.at(i) );};
	//! see STL
	void resize(size_t n)					
	{   
		CSingleLock s(&m_mutex); 
		s.Lock(); 
		if (s.IsLocked()) 
		{ m_v.resize(n); s.Unlock();} 
	};
	//! clear object
	void clear()							
	{	
		CSingleLock s(&m_mutex); 
		s.Lock(); 
		if (s.IsLocked()) 
		{ m_v.clear(); s.Unlock();} 
	};
	//@}

	//! \name STL vector access and manipulation
	//@{
	//! setting the vector content
	void SetV(const VectorT& v)	{	m_v=v;};
	//! return the STL vector 
	VectorT& GetV()				{	return m_v;};
	//! returns the STL vector, const
	const VectorT& GetV() const	{	return m_v;};
	//! access operator, reference
	reference operator [](size_t i)				
	{   return m_v.at(i);};
	//!  accessing an elelment of the vector
	reference at(size_t i) 						
	{	ASSERT(i<m_v.size()); return m_v.at(i);};
	//@}
	

protected:
	//! \name Attributes
	//@{
	//! STL vector.
	std::vector<T> m_v;
	//@}
};



#ifndef PGL_DECLARE_VECTOR_DATA_TYPE
	#define PGL_DECLARE_VECTOR_DATA_TYPE( className , classType)\
	class PGLCORE_EXT_CLASS className : public CPGLVector<classType>\
	{ \
	PGL_DECLARE_DATA_TYPE( className, CPGLVector<classType>, true, true); \
	public: \
		className (); \
		className (size_t n);\
		className (const VectorT& v);\
		className (const classType* v, size_t n);\
		className (const className & v);\
		className & operator = (const className & v);\
	}; \
	PGL_DECLARE_SMARTPTR( className )
#endif

/*! \class CPGLVectorD
	\brief A vector of double
	\sa CPGLVector
  \ingroup PGLTempVectorGroup
*/
/*! \class CPGLVectorF
	\brief A vector of float
	\sa CPGLVector
  \ingroup PGLTempVectorGroup
*/
/*! \class CPGLVectorI
	\brief A vector of int
	\sa CPGLVector
  \ingroup PGLTempVectorGroup
*/
/*! \class CPGLVectorB
	\brief A vector of BYTE
	\sa CPGLVector
  \ingroup PGLTempVectorGroup
*/
/*! \class CPGLVectorS
	\brief A vector of short
	\sa CPGLVector
  \ingroup PGLTempVectorGroup
*/
/*! \class CPGLVectorL
	\brief A vector of long
	\sa CPGLVector
  \ingroup PGLTempVectorGroup
*/

PGL_DECLARE_VECTOR_DATA_TYPE(CPGLVectorD, double)
PGL_DECLARE_VECTOR_DATA_TYPE(CPGLVectorF, float)
PGL_DECLARE_VECTOR_DATA_TYPE(CPGLVectorB, BYTE)
PGL_DECLARE_VECTOR_DATA_TYPE(CPGLVectorI, int)
PGL_DECLARE_VECTOR_DATA_TYPE(CPGLVectorS, short)
PGL_DECLARE_VECTOR_DATA_TYPE(CPGLVectorL, long)

/*!
	\defgroup PGLTempVectorRefGroup Vector, based on a reference to STL vector.
\ingroup PGLDataGroup
*/

/*! \brief A reference to a vector template

	<p>This object stores a reference to an existing vector. No manipulation is made on this vector (declared as const).</p>
\par Serialization

The object cannot serialize the reference, hence it is serialized as a CPGLVector<T>.
	
  \ingroup PGLTempVectorRefGroup
*/
template <class T>
class PGLCORE_EXT_CLASS CPGLVectorRef : public CPGLData
{
public:
	//! \name Type definition
	//@{
	typedef T value_type;
	typedef T& reference;
	//! Vector of T
	typedef std::vector<T> VectorT;
	//@}

	//! \name Constructors
	//@{
	//! Default constructor
	CPGLVectorRef<T>():m_pV(NULL){};
	//! Construct from reference to v, v must be valid
	CPGLVectorRef<T>(const VectorT& v) : m_pV(&v){};
	//! Construct from handle pV, pV must be valid
	CPGLVectorRef<T>(const VectorT* pV): m_pV(pV){};
	//! Copy constructor
	CPGLVectorRef<T>(const CPGLVectorRef<T>& v):m_pV(NULL)	
	{	*this = v;};
	//! Assignement constructor
	CPGLVectorRef<T>& operator = (const CPGLVectorRef<T>& v)
	{	if (this != &v) { m_pV = v.m_pV;} return *this;};
	virtual ~CPGLVectorRef<T>() {};
	//@}

	//! \name Virtual overrides
	//@{
	//! returns the size of the vector
	size_t size() const						
	{	if (!m_pV) return 0; return m_pV->size();};
	//! member access, cosnt
	float operator[](size_t i) const 		
	{	return at(i);};
	//! member access, cosnt
	float at(size_t i) const				
	{	ASSERT(m_pV); ASSERT(i<m_pV->size()); 
		return static_cast<float>(m_pV->at(i));
	};
	//! clear data
	void clear()							
	{	m_pV=NULL;};
	//@}

	//! \name Vector manipulation
	//@{
	//! Setting the reference
	void SetV(const VectorT& v)	{	m_pV=&v;};
	//! returns the reference vector
	const VectorT& GetV() const	{	return *m_pV;};
	//@}
	
protected:
	//! \name Attributes
	//@{
	//! pointer to vector
	const VectorT* m_pV;
	//@}
};

#define PGL_DECLARE_VECTORREF_DATA_TYPE( className , classType) \
class PGLCORE_EXT_CLASS className : public CPGLVectorRef< classType > \
{ \
PGL_DECLARE_DATA_TYPE( className, CPGLVectorRef< classType >, false, true); \
public: \
	className () {}; \
	className (const VectorT& v) : CPGLVectorRef< classType > (v){}; \
	className (const VectorT* pV) : CPGLVectorRef< classType > (pV) {}; \
	className (const className & v)					{	*this = v;}; \
	className & operator = (const className & v) \
	{	if (this != &v) { this->CPGLVectorRef< classType >::operator =(v); } return *this;}; \
};\
PGL_DECLARE_SMARTPTR( className )

/*! \class CPGLVectorRefD
	\brief A reference to a vector of double
	\sa CPGLVectorRef
  \ingroup PGLTempVectorRefGroup
*/
/*! \class CPGLVectorRefF
	\brief A reference to a vector of float
	\sa CPGLVectorRef
  \ingroup PGLTempVectorRefGroup
*/
/*! \class CPGLVectorRefI
	\brief A reference to a vector of int
	\sa CPGLVectorRef
  \ingroup PGLTempVectorRefGroup
*/
/*! \class CPGLVectorRefU
	\brief A reference to a vector of size_t
	\sa CPGLVectorRef
  \ingroup PGLTempVectorRefGroup
*/
/*! \class CPGLVectorRefB
	\brief A reference to a vector of BYTE
	\sa CPGLVectorRef
  \ingroup PGLTempVectorRefGroup
*/
/*! \class CPGLVectorRefS
	\brief A reference to a vector of short
	\sa CPGLVectorRef
  \ingroup PGLTempVectorRefGroup
*/
/*! \class CPGLVectorRefL
	\brief A reference to a vector of long
	\sa CPGLVectorRef
  \ingroup PGLTempVectorRefGroup
*/


PGL_DECLARE_VECTORREF_DATA_TYPE( CPGLVectorRefD, double)
PGL_DECLARE_VECTORREF_DATA_TYPE( CPGLVectorRefF, float)
PGL_DECLARE_VECTORREF_DATA_TYPE( CPGLVectorRefB, BYTE)
PGL_DECLARE_VECTORREF_DATA_TYPE( CPGLVectorRefI, int)
PGL_DECLARE_VECTORREF_DATA_TYPE( CPGLVectorRefS, short)
PGL_DECLARE_VECTORREF_DATA_TYPE( CPGLVectorRefL, long)



/*! \brief A wrapper around a C Array

*/
template <typename T>
class PGLCORE_EXT_CLASS CPGLCArray : public CPGLData
{
public:
	//! \name Type definition
	//@{
	typedef T value_type;
	typedef T& reference;
	typedef T* pointer;
	//@}

	//! \name Constructors
	//@{
	//! Default constructor
	CPGLCArray()
		: m_data(NULL),m_size(0){};
	CPGLCArray(CPGLCArray<T> const& c_)
		: m_data(c_.m_data),m_size(c_.m_size){};
	//! Construct from array
	CPGLCArray(
		pointer data_, 
		size_t size_
		)
		: 
	m_data(data_), 
		m_size(size_)
	{};
	//@}

	//! \name Virtual overrides
	//@{
	//! return the size of the vector
	size_t size() const {	return m_size;};
	//! index accessor
	float operator [](size_t i)	const	
	{	return at(i);};
	//!  accessing an elelment of the vector
	float at(size_t i) const				
	{	ASSERT(i<m_size); return static_cast<float>( m_data[i] );};
	void clear() 
	{	m_size=0;};
	//@}

	void set_data(
		pointer data_, 
		size_t size_
		)
	{
		m_size = size_;
		m_data=data_;
	}

protected:
	//! \name Attributes
	//@{
	pointer m_data;
	size_t m_size;
	//@}
};

#ifndef PGL_DECLARE_CARRAY_DATA_TYPE
#define PGL_DECLARE_CARRAY_DATA_TYPE( className , classType)\
class PGLCORE_EXT_CLASS className : public CPGLCArray<classType>\
{ \
	PGL_DECLARE_DATA_TYPE( className, CPGLCArray<classType>, true, true); \
public: \
	className (); \
	className (pointer data_, size_t size_);\
	className (className const&);\
}; \
PGL_DECLARE_SMARTPTR( className )
#endif

PGL_DECLARE_CARRAY_DATA_TYPE(CPGLCArrayD, double)
PGL_DECLARE_CARRAY_DATA_TYPE(CPGLCArrayF, float)
PGL_DECLARE_CARRAY_DATA_TYPE(CPGLCArrayB, BYTE)
PGL_DECLARE_CARRAY_DATA_TYPE(CPGLCArrayI, int)
PGL_DECLARE_CARRAY_DATA_TYPE(CPGLCArrayS, short)
PGL_DECLARE_CARRAY_DATA_TYPE(CPGLCArrayL, long)

#endif // !defined(AFX_PGLDATAVECTORS_H__2D102127_B7D4_4614_A440_0DF7151346D1__INCLUDED_)
